/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package mathma.core.cond.form;

import mathma.core.bool.BooleanValue;

import mathma.core.cond.Conditional;

import mathma.core.expr.Expression;

import mathma.core.form.FormulaicExpression;
import mathma.core.form.TypeConversionExpression;

import mathma.core.value.Value;

import java.util.ArrayList;
import java.util.List;

/**
 * @since 0.2.5
 * @author Ethan Levine
 */
public class IfElseExpression<E extends Value, O extends Value>
        extends FormulaicExpression<E, E> {

    private final Conditional<O> test;
    private final Expression<E> trueExpr;
    private final Expression<E> falseExpr;

    public IfElseExpression(Conditional<O> test, Expression<E> trueExpr,
            Expression<E> falseExpr) {
        super(trueExpr.getType());
        this.test = test;
        this.trueExpr = trueExpr;
        this.falseExpr = falseExpr;
    }

    public E evaluate() {
        if (test.evaluate().getRawValue()) {
            return trueExpr.evaluate();
        } else {
            return falseExpr.evaluate();
        }
    }

    public List<Expression<E>> getOperands() {
        List<Expression<E>> operands = new ArrayList<Expression<E>>();
        operands.add(new TypeConversionExpression<E, BooleanValue>(getType(), test));
        operands.add(trueExpr);
        operands.add(falseExpr);
        return operands;
    }

    public IfElseExpression<E, O> newInstance(List<Expression<E>> operands) {
        if (operands.size() == 3 &&
                operands.get(0).getClass().equals(TypeConversionExpression.class)) {
            return new IfElseExpression<E, O>((Conditional<O>)
                    ((TypeConversionExpression<E, O>) operands.get(0)).getOperand(),
                    operands.get(1), operands.get(2));
        } else {
            throw new IllegalArgumentException(
                    "Invalid argument to IfElseExpression.newInstance.");
        }
    }
}
